#include <algorithm>
#include <iostream>
#include <cassert>

#include "binarystream.h"
#include "annotateoptions.h"

CHTMLOptions::CHTMLOptions()
	:
	m_HTMLSampleFont(false),
	m_HTMLBrowserFontSize(false),
	m_HTMLWebSafeColours(false),
	m_HTMLStyleSheets(COptions::S_CSS),
	m_ColourPalette(COptions::C_40)
{}

CAnnotateOptions::CAnnotateOptions()
	:
	m_XForUnknown(true),
	m_IncludeBlanks(true),
	m_UseElision(true),
	m_ConsensusThreshold(800),
	m_MinElisionLength(4),
	m_ElisionThreshold(800)
{}

CParseOptions::CParseOptions()
	:
	m_ConfirmDataFormats(false),
	m_MergePHDPredictions(true),
	m_IgnoreConfidences(false),
	m_Ignore_COIL(false),
	m_AllowLowerCase(false),
	m_AllowStrangeLinkers(false),
	m_OnlyValidAAs(VALID_ALL),
	m_InvalidResidueLetters("")
{}

COutputOptions::COutputOptions()
	:	
	m_ColumnWidth(0),
	m_WrapOutputLen(80),
	m_SubstitutedLinkers("-_~."),
	m_WrapOutput(true),
	m_OutputConsensusThreshold(true),
	m_ForceToUpper(true),
	m_SubstituteLinker(true),
	m_ColumnSpaces(false),
	m_SetDuplicates(false),
	m_MultipleSets(false),
	m_SubstitutingLinker('-'),
	m_JustifyName(JUSTIFY_L)
{}

CGeneralOptions::CGeneralOptions()
:	m_MRUCount(0),
	m_MRUConfigCount(0),
	m_ToolbarLarge(false),
	m_Verbose(false)
{}


//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		Utility functions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
namespace
{
void setrange(unsigned& a, unsigned Min, unsigned Max)
{
	if (a < Min)
		a = Min;
	else if (a > Max)
		a = Max;
}
struct ToUpper {void operator()(char & c){toupper(c);}};
struct NotIsUpper{	int operator()(char c) {return !isupper(c);}};
struct NotIsPunct{	int operator()(char c) {return !ispunct(c);}};
void UniqueStringUpper_or_Punct(std::string& s, bool upper)
{
	std::string::iterator b = s.begin();
	std::string::iterator e = s.end();
	if (upper)
		std::for_each(b, e, ToUpper());
	if (upper)
		std::replace_if(b, e, NotIsUpper(), '\254');
	else
		std::replace_if(b, e, NotIsPunct(), '\254');
	b  = std::unique(b, e);
	if (b != e && *b == '\254')
		--b;
	s.erase(b, e);
}

bool str_to_long(const std::string& str, long& return_val)
{
	char* end = 0;
	return_val = strtol(str.c_str(), &end, 10);
	return *end == 0;
}

bool str_to_bool(const std::string& str, bool default_val)
{
	long l;
	if (str_to_long(str, l))
		return l != 0;
	else
		return default_val;
}

}


//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		Validation functions (IS_VALID)
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
#ifndef NDEBUG

bool CHTMLOptions::IS_VALID() const
{
	if(	m_HTMLStyleSheets != S_CSS &&
		m_HTMLStyleSheets != S_INLINE)
		return false;
	if(	m_ColourPalette != C_40 &&
		m_ColourPalette != C_216	)
		return false;
	return true;
}

bool CAnnotateOptions::IS_VALID() const
{
	if (m_ElisionThreshold > 1000)
		return false;
	if (m_MinElisionLength < 4 || m_MinElisionLength > 9999)
		return false;
	if (m_ConsensusThreshold <= 500 || m_ConsensusThreshold > 1000)
		return false;
	return true;
}


bool CParseOptions::IS_VALID() const
{
	if (m_OnlyValidAAs != VALID_CUST &&
		m_OnlyValidAAs != VALID_STD &&
		m_OnlyValidAAs != VALID_ALL)
		return false;
	std::string temp = m_InvalidResidueLetters;
	UniqueStringUpper_or_Punct(temp, true);
	if (temp != m_InvalidResidueLetters)
		return false;
	return true;
}

bool COutputOptions::IS_VALID() const
{
	if (m_ColumnWidth < 2 || m_ColumnWidth > 9999)
		return false;
	if (m_WrapOutputLen < 2 || m_WrapOutputLen > 9999)
		return false;
	if (m_SubstitutingLinker == 0)
		return false;
	if (m_JustifyName != JUSTIFY_L &&
		m_JustifyName != JUSTIFY_C &&
		m_JustifyName != JUSTIFY_R)
		return false;

	// make sure no duplicates
	std::string temp = m_SubstitutedLinkers;
	bool valid = (std::unique(temp.begin(), temp.end()) == temp.end());
	return valid;
}
bool CGeneralOptions::IS_VALID() const
{
	if (m_MRUCount > 16)
		return false;
	if (m_MRUConfigCount > 16)
		return false;
	return true;
}


#endif



//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		MFC functions for writing to and from the registry
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888







#ifdef _MFC_VER

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CHTMLOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
void CHTMLOptions::ToRegistry(CWinApp* app)
{
	CString section = "HTML Settings";
	app->WriteProfileInt(section, "Use \"SAMPLE\" font", m_HTMLSampleFont);
	app->WriteProfileInt(section, "Use Browser Font Size Settings", m_HTMLBrowserFontSize);
	app->WriteProfileInt(section, "Check for web-safe colours", m_HTMLWebSafeColours);
	app->WriteProfileInt(section, "Use style Sheets", m_HTMLStyleSheets);
	app->WriteProfileInt(section, "Colour Palette", m_ColourPalette);
}


void CHTMLOptions::FromRegistry(CWinApp* app)
{
	CString section = "HTML Settings";
	m_HTMLSampleFont		= app->GetProfileInt(section, "Use \"SAMPLE\" font", true) != 0;
	m_HTMLBrowserFontSize	= app->GetProfileInt(section, "Use Browser Font Size Settings", true) != 0;
	m_HTMLWebSafeColours	= app->GetProfileInt(section, "Check for web-safe colours", true) != 0;
							  unsigned htmlStyleSheets	
							= app->GetProfileInt(section, "Use style Sheets", 0);
							  htmlStyleSheets = std::min(htmlStyleSheets, 1U);
	m_HTMLStyleSheets		= (HTMLSTYLES_FLAG)htmlStyleSheets;
							  unsigned colourPalette		
							= app->GetProfileInt(section, "Colour Palette", 0);
							  colourPalette	= std::min(colourPalette, 1U);
	m_ColourPalette			= (COLOURPALETTE_FLAG)colourPalette;
}

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CAnnotateOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
void CAnnotateOptions::ToRegistry(CWinApp* app)
{
	CString section = "Annotation Settings";
	app->WriteProfileInt(section, "X is for Unknown", m_XForUnknown);
	app->WriteProfileInt(section, "Consensus Threshold", m_ConsensusThreshold);
	app->WriteProfileInt(section, "Include Blanks", m_IncludeBlanks);
	app->WriteProfileInt(section, "Use Elision", m_UseElision);
	app->WriteProfileInt(section, "Minimum Elision Length", m_MinElisionLength);
	app->WriteProfileInt(section, "Elision Threshold", m_ElisionThreshold);
}

void CAnnotateOptions::FromRegistry(CWinApp* app)
{
	// defaults:
	//		threshold					= 80%
	//		include gaps
	//		X = unknown
	//		Use Elision
	//		Minimum Elision length		= 4
	//		Minimum Elision threshold	= 80%
	CString section = "Annotation Settings";
	m_IncludeBlanks			= app->GetProfileInt(section, "Include Blanks", true)!=0;
	m_XForUnknown			= app->GetProfileInt(section, "X is for Unknown", true)!=0;
	m_ConsensusThreshold	= app->GetProfileInt(section, "Consensus Threshold", 800);
							  setrange(m_ConsensusThreshold, 500, 1000);
	m_UseElision			= app->GetProfileInt(section, "Use Elision", 1) !=0;
	m_MinElisionLength		= app->GetProfileInt(section, "Minimum Elision Length", 4);
							  setrange(m_MinElisionLength, 4, 9999);
	m_ElisionThreshold		= app->GetProfileInt(section, "Elision Threshold", 800);
							  m_ElisionThreshold = std::min(m_ElisionThreshold, 1000U);
}

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CParseOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
void CParseOptions::ToRegistry(CWinApp* app)
{
	CString section = "Parse Settings";
	app->WriteProfileInt(section, "DSC Ignore Coil", m_Ignore_COIL);
	app->WriteProfileInt(section, "Merge PHD predictions", m_MergePHDPredictions);
	app->WriteProfileInt(section, "Restrict to Valid AAs", m_OnlyValidAAs);
	app->WriteProfileString(section, "Invalid Residues", m_InvalidResidueLetters.c_str());
	app->WriteProfileInt(section, "Confirm Data Formats", m_ConfirmDataFormats);
	app->WriteProfileInt(section, "Allow lower case", m_AllowLowerCase);
	app->WriteProfileInt(section, "Allow strange linkers", m_AllowStrangeLinkers);
	app->WriteProfileInt(section, "Ignore 2ndary struct confidences", m_IgnoreConfidences);
}

void CParseOptions::FromRegistry(CWinApp* app)
{
	CString section = "Parse Settings";
	m_Ignore_COIL			= app->GetProfileInt(section, "DSC Ignore Coil", true)!=0;
	m_MergePHDPredictions	= app->GetProfileInt(section, "Merge PHD predictions", true)!=0;
							  unsigned validAAs
							= app->GetProfileInt(section, "Restrict to Valid AAs", 0);
							  validAAs				= std::min(validAAs, 2U);
	m_OnlyValidAAs			= (VALIDRES_FLAG)validAAs;
	m_InvalidResidueLetters = app->GetProfileString(section, "Invalid Residues", "BJOUZ");
							  UniqueStringUpper_or_Punct(m_InvalidResidueLetters, true);
	m_ConfirmDataFormats	= app->GetProfileInt(section, "Confirm Data Formats", true)!=0;
	m_AllowLowerCase		= app->GetProfileInt(section, "Allow lower case", false)!=0;
	m_AllowStrangeLinkers	= app->GetProfileInt(section, "Allow strange linkers", false)!=0;
	m_IgnoreConfidences		= app->GetProfileInt(section, "Ignore 2ndary struct confidences", true)!=0;
}

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		COutputOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
void COutputOptions::ToRegistry(CWinApp* app)
{
	CString section = "Output Settings";
	app->WriteProfileInt(section, "Column width", m_ColumnWidth);
	app->WriteProfileInt(section, "Wrap Output Length", m_WrapOutputLen);

	app->WriteProfileString(section, "Substituted Linkers", m_SubstitutedLinkers.c_str());


	app->WriteProfileInt(section, "Wrap Output", m_WrapOutput);
	app->WriteProfileInt(section, "Output Consensus Threshold", m_OutputConsensusThreshold);
	app->WriteProfileInt(section, "Enforce Upper", m_ForceToUpper);
	app->WriteProfileInt(section, "Enforce Linker Character", m_SubstituteLinker);
	app->WriteProfileInt(section, "Separate columns with spaces", m_ColumnSpaces);
	app->WriteProfileInt(section, "Duplicate sequences in sets", m_SetDuplicates);
	app->WriteProfileInt(section, "Multiple alignment sets", m_MultipleSets);

	app->WriteProfileInt(section, "Substituting Linker Character", m_SubstitutingLinker);

	app->WriteProfileInt(section, "Name Justification", m_JustifyName);
}

void COutputOptions::FromRegistry(CWinApp* app)
{
	// defaults:
	//		Convert to Upper case
	//		Substitute Gap symbols
	//		Substituted Gap symbols		= -_~.
	//		Substituting Gap symbols	= -
	//		Left justify
	//		Wrap output
	//		Wrap output every 60 characters
	//		Write consensus threshold value
	//		Do NOT use column spaces
	//		column width				= 10
	//		Use multiple sets			= false
	//		Allow duplicates in sets	= false
	CString section = "Output Settings";
	m_ForceToUpper			= app->GetProfileInt(section, "Enforce Upper", true)!=0;
	m_SubstituteLinker		= app->GetProfileInt(section, "Enforce Linker Character", true)!=0;
	m_SubstitutedLinkers	= app->GetProfileString(section, "Substituted Linkers", "-_~.");
							  UniqueStringUpper_or_Punct(m_SubstitutedLinkers, false);
							  unsigned substitutingLinker
							= app->GetProfileInt(section, "Substituting Linker Character", '-');
							  setrange(substitutingLinker, 0, 255);
	m_SubstitutingLinker	= (unsigned char)substitutingLinker;
							  unsigned justifyName		
							= app->GetProfileInt(section, "Name Justification", 0);
							  setrange(justifyName, 0, 2);
	m_JustifyName			= (JUSTIFY_FLAG)justifyName;
	m_WrapOutput			= app->GetProfileInt(section, "Wrap Output", 1) !=0;
	m_WrapOutputLen			= app->GetProfileInt(section, "Wrap Output Length", 60);
	m_WrapOutputLen			= std::min(m_WrapOutputLen, 9999U);
	m_OutputConsensusThreshold = app->GetProfileInt(section, "Output Consensus Threshold", 1) !=0;
	m_ColumnSpaces			= app->GetProfileInt(section, "Separate columns with spaces", 0)!=0;
	m_ColumnWidth			= app->GetProfileInt(section, "Column width", 10);
							  setrange(m_ColumnWidth, 2, 9999);
	m_SetDuplicates			= app->GetProfileInt(section, "Duplicate sequences in sets", false)!=0;
	m_MultipleSets			= app->GetProfileInt(section, "Multiple alignment sets", false)!=0;
}


//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CGeneralOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
void CGeneralOptions::ToRegistry(CWinApp* app)
{
	CString	section = "General Settings";
	app->WriteProfileInt(section, "Large toolbar buttons", m_ToolbarLarge);
	app->WriteProfileInt(section, "Verbose dialogues", m_Verbose);
	app->WriteProfileInt(section, "MRU Documents Count", m_MRUCount);
	app->WriteProfileInt(section, "MRU Configurations Count", m_MRUConfigCount);
}

void CGeneralOptions::FromRegistry(CWinApp* app)
{
	CString	section = "General Settings";
	m_ToolbarLarge			= app->GetProfileInt(section, "Large toolbar buttons", 1) !=0;
	m_Verbose				= app->GetProfileInt(section, "Verbose dialogues", 1) !=0;
	m_MRUCount				= app->GetProfileInt(section, "MRU Documents Count", 9);
	m_MRUCount				= std::min(m_MRUCount, 16U);
	m_MRUConfigCount		= app->GetProfileInt(section, "MRU Configurations Count", 9);
	m_MRUConfigCount		= std::min(m_MRUConfigCount, 16U);
}

#endif // _MFC_VER


//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CHTMLOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
bool CHTMLOptions::set_bool(unsigned int index, const std::string& str)
{
	switch (index)
	{
		case eHTMLSampleFont:
			m_HTMLSampleFont = str_to_bool(str, m_HTMLSampleFont);
			return true;
		case eHTMLBrowserFontSize:
			m_HTMLBrowserFontSize = str_to_bool(str, m_HTMLBrowserFontSize);
			return true;
		case eHTMLWebSafeColours:
			m_HTMLWebSafeColours = str_to_bool(str, m_HTMLWebSafeColours);
			return true;
	}
	return false;
};

bool CHTMLOptions::set_flag(unsigned int index, const std::string& str)
{
	long result;
	if (!str_to_long(str, result) || result < 0)
		return false;
	
	switch (index)
	{
		case eHTMLStyleSheets:
			m_HTMLStyleSheets = (HTMLSTYLES_FLAG) std::min ((long)S_CSS, result);
			return true;

		case eColourPalette:
			m_ColourPalette = (COLOURPALETTE_FLAG) std::min ((long)C_216, result);
			return true;
	}
	return false;
};

void CHTMLOptions::init_optionsmap(Cmap_options& opt)
{
	// bool
	opt.insert(Cmap_options::value_type("Use \"SAMPLE\" font",
				CLookup_SetOption(eOPT_B, eHTMLSampleFont, *this)));
	opt.insert(Cmap_options::value_type("Use Browser Font Size Settings",
				CLookup_SetOption(eOPT_B, eHTMLBrowserFontSize, *this)));
	opt.insert(Cmap_options::value_type("Check for web-safe colours",
				CLookup_SetOption(eOPT_B, eHTMLWebSafeColours, *this)));

	// flags
	opt.insert(Cmap_options::value_type( "Use style Sheets",
			CLookup_SetOption(eOPT_F, eHTMLStyleSheets, *this)));
	opt.insert(Cmap_options::value_type( "Colour Palette",
			CLookup_SetOption(eOPT_F, eColourPalette, *this)));

}

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CAnnotateOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
bool CAnnotateOptions::set_bool(unsigned int index, const std::string& str)
{
	switch (index)
	{
		case eXForUnknown:
			m_XForUnknown = str_to_bool(str, m_XForUnknown);
			return true;
		case eIncludeBlanks:
			m_IncludeBlanks = str_to_bool(str, m_IncludeBlanks);
			return true;
		case eUseElision:
			m_UseElision = str_to_bool(str, m_UseElision);
			return true;
	}
	return false;
}

bool CAnnotateOptions::set_uint(unsigned int index, const std::string& str)
{
	long result;
	if (!str_to_long(str, result) || result < 0)
		return false;
	
	switch (index)
	{
		case eConsensusThreshold:
			m_ConsensusThreshold = result;
			setrange(m_ConsensusThreshold, 500, 1000);
			return true;
	
		case eMinElisionLength:
			m_MinElisionLength = result;
			setrange(m_MinElisionLength, 4, 9999);
			return true;
			
		case eElisionThreshold:
			m_ElisionThreshold = static_cast<unsigned>(std::min(result, 1000L));
			return true;
	}
	return false;

}

void CAnnotateOptions::init_optionsmap(Cmap_options& opt)
{
	// bools
	opt.insert(Cmap_options::value_type( "X is for Unknown",
			CLookup_SetOption(eOPT_B, eXForUnknown, *this)));
	opt.insert(Cmap_options::value_type( "Include Blanks",
			CLookup_SetOption(eOPT_B, eIncludeBlanks, *this)));
			opt.insert(Cmap_options::value_type( "Use Elision",
					CLookup_SetOption(eOPT_B, eUseElision, *this)));

	// flags
	opt.insert(Cmap_options::value_type( "Consensus Threshold",
			CLookup_SetOption(eOPT_U, eConsensusThreshold, *this)));
	opt.insert(Cmap_options::value_type( "Minimum Elision Length",
			CLookup_SetOption(eOPT_U, eMinElisionLength, *this)));
	opt.insert(Cmap_options::value_type( "Elision Threshold",
			CLookup_SetOption(eOPT_U, eElisionThreshold, *this)));
}			

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		CParseOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
bool CParseOptions::set_bool(unsigned int index, const std::string& str)
{
	switch (index)
	{
		case eMergePHDPredictions:
			m_MergePHDPredictions = str_to_bool(str, m_MergePHDPredictions);
			return true;

		case eIgnoreConfidences:
			m_IgnoreConfidences = str_to_bool(str, m_IgnoreConfidences);
			return true;

		case eIgnore_COIL:
			m_Ignore_COIL = str_to_bool(str, m_Ignore_COIL);
			return true;

		case eAllowLowerCase:
			m_AllowLowerCase = str_to_bool(str, m_AllowLowerCase);
			return true;

		case eAllowStrangeLinkers:
			m_AllowStrangeLinkers = str_to_bool(str, m_AllowStrangeLinkers);
			return true;

	}
	return false;
}

bool CParseOptions::set_flag(unsigned int index, const std::string& str)
{
	long result;
	if (!str_to_long(str, result) || result < 0 || index != eOnlyValidAAs)
		return false;
	m_OnlyValidAAs = (VALIDRES_FLAG) std::min (2L, result);
	return true;
};

bool CParseOptions::set_str(unsigned int index, const std::string& str)
{
	if (index != eInvalidResidueLetters)
		return(false);

	// only accept upper case letters or punctuation without duplications
	std::string temp = str;	
	UniqueStringUpper_or_Punct(temp, true);
	if (temp != str)
		return false;
	m_InvalidResidueLetters = str;
	return(true);
}

void CParseOptions::init_optionsmap(Cmap_options& opt)
{
	// bool
	opt.insert(Cmap_options::value_type( "Merge PHD predictions",
			CLookup_SetOption(eOPT_B, eMergePHDPredictions, *this)));
	opt.insert(Cmap_options::value_type( "Ignore 2ndary struct confidences",
			CLookup_SetOption(eOPT_B, eIgnoreConfidences, *this)));
	opt.insert(Cmap_options::value_type( "DSC Ignore Coil",
			CLookup_SetOption(eOPT_B, eIgnore_COIL, *this)));
	opt.insert(Cmap_options::value_type( "Allow lower case",
			CLookup_SetOption(eOPT_B, eAllowLowerCase, *this)));
	opt.insert(Cmap_options::value_type( "Allow strange linkers",
			CLookup_SetOption(eOPT_B, eAllowStrangeLinkers, *this)));

	// flags
	opt.insert(Cmap_options::value_type( "Restrict to Valid AAs",
			CLookup_SetOption(eOPT_F, eOnlyValidAAs, *this)));

	// strings
	opt.insert(Cmap_options::value_type( "Invalid Residues",
			CLookup_SetOption(eOPT_S, eInvalidResidueLetters, *this)));
}


//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//		COutputOptions
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
bool COutputOptions::set_bool(unsigned int index, const std::string& str)
{
	switch (index)
	{
		case eWrapOutput:
			m_WrapOutput = str_to_bool(str, m_WrapOutput);
			return true;

		case eOutputConsensusThreshold:
			m_OutputConsensusThreshold = str_to_bool(str, m_OutputConsensusThreshold);
			return true;

		case eForceToUpper:
			m_ForceToUpper = str_to_bool(str, m_ForceToUpper);
			return true;

		case eSubstituteLinker:
			m_SubstituteLinker = str_to_bool(str, m_SubstituteLinker);
			return true;

		case eColumnSpaces:
			m_ColumnSpaces = str_to_bool(str, m_ColumnSpaces);
			return true;

		case eSetDuplicates:
			m_SetDuplicates = str_to_bool(str, m_SetDuplicates);
			return true;

		case eMultipleSets:
			m_MultipleSets = str_to_bool(str, m_MultipleSets);
			return true;
	}
	return false;
}


bool COutputOptions::set_uint(unsigned int index, const std::string& str)
{
	long l;
	if (!str_to_long(str, l) || l< 0)
		return false;
	switch(index)
	{
		case eWrapOutputLen:
			m_WrapOutputLen = static_cast<unsigned>(std::min(l, 9999L));
			return true;
		case eColumnWidth:
			m_ColumnWidth = l;
			setrange(m_ColumnWidth, 2, 9999);
			return true;
	}
	return false;
}


bool COutputOptions::set_flag(unsigned int index, const std::string& str)
{
	long result;
	if (!str_to_long(str, result) || result < 0 || index != eJustifyName)
		return false;
	m_JustifyName = (JUSTIFY_FLAG) std::min (2L, result);
	return true;
};


bool COutputOptions::set_str(unsigned int index, const std::string& str)
{
	switch (index)
	{
		case eSubstitutedLinkers:
			m_SubstitutedLinkers = str;
			UniqueStringUpper_or_Punct(m_SubstitutedLinkers, false);
			return true;
		case eSubstitutingLinker:
			if (str.length() != 1)
				return(false);
			m_SubstitutingLinker = str[0];
			return true;
	}
	return(false);
}

void COutputOptions::init_optionsmap(Cmap_options& opt)
{
	// uint
	opt.insert(Cmap_options::value_type( "Column width",
			CLookup_SetOption(eOPT_U, eColumnWidth, *this)));
	opt.insert(Cmap_options::value_type( "Wrap Output Length",
			CLookup_SetOption(eOPT_U, eWrapOutputLen, *this)));

	// str
	opt.insert(Cmap_options::value_type( "Substituted Linkers",
			CLookup_SetOption(eOPT_S, eSubstitutedLinkers, *this)));
	// char
	opt.insert(Cmap_options::value_type( "Substituting Linker Character",
			CLookup_SetOption(eOPT_S, eSubstitutingLinker, *this)));


	// bool
	opt.insert(Cmap_options::value_type( "Wrap Output",
			CLookup_SetOption(eOPT_B, eWrapOutput, *this)));
	opt.insert(Cmap_options::value_type( "Output Consensus Threshold",
			CLookup_SetOption(eOPT_B, eOutputConsensusThreshold, *this)));
	opt.insert(Cmap_options::value_type( "Enforce Upper",
			CLookup_SetOption(eOPT_B, eForceToUpper, *this)));
	opt.insert(Cmap_options::value_type( "Enforce Linker Character",
			CLookup_SetOption(eOPT_B, eSubstituteLinker, *this)));
	opt.insert(Cmap_options::value_type( "Separate columns with spaces",
			CLookup_SetOption(eOPT_B, eColumnSpaces, *this)));
	opt.insert(Cmap_options::value_type( "Duplicate sequences in sets",
			CLookup_SetOption(eOPT_B, eSetDuplicates, *this)));
	opt.insert(Cmap_options::value_type( "Multiple alignment sets",
			CLookup_SetOption(eOPT_B, eMultipleSets, *this)));


	// flag
	opt.insert(Cmap_options::value_type( "Name Justification",
			CLookup_SetOption(eOPT_F, eJustifyName, *this)));

}

